package com.evil.application.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.application.mapper.ApplicationFormControlMapper;
import com.evil.application.mapper.ApplicationFormControlRelatedMapper;
import com.evil.application.pojo.dto.form.control.related.ControlRelatedDTO;
import com.evil.application.pojo.entity.ApplicationFormControl;
import com.evil.application.pojo.entity.ApplicationFormControlRelated;
import com.evil.application.service.ApplicationFormControlRelatedService;
import com.evil.common.application.enums.form.DefaultValueTypeEnum;
import com.evil.common.core.util.StreamUtil;
import com.evil.common.core.enums.SwitchEnum;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 应用表单控件关联表
 *
 * @author liyang
 * @date 2023-09-25 15:14
 */
@Service
@AllArgsConstructor
public class ApplicationFormControlRelatedServiceImpl extends ServiceImpl<ApplicationFormControlRelatedMapper, ApplicationFormControlRelated>
        implements ApplicationFormControlRelatedService {

    private final ApplicationFormControlMapper applicationFormControlMapper;
    private final ApplicationLogServiceImpl logService;

    @Override
    public int updateBatch(List<ApplicationFormControlRelated> list) {
        return baseMapper.updateBatch(list);
    }

    @Override
    public int batchInsert(List<ApplicationFormControlRelated> list) {
        return baseMapper.batchInsert(list);
    }

    /**
     * 获取控件关联
     *
     * @param controlId     controlId
     * @param filterDeleted filterDeleted
     * @return ControlRelatedDTO 列表
     */
    @Override
    public List<ApplicationFormControlRelated> findByControlId(Long controlId, boolean filterDeleted) {
        return this.baseMapper.findByControlId(controlId, filterDeleted);
    }

    /**
     * 获取控件关联
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return ControlRelatedDTO 列表
     */
    @Override
    public List<ApplicationFormControlRelated> findByControlIds(Collection<Long> controlIds, boolean filterDeleted) {
        return this.baseMapper.findByControlIds(controlIds, filterDeleted);
    }

    /**
     * 获取控件关联
     *
     * @param controlId     controlId
     * @param filterDeleted filterDeleted
     * @return ControlRelatedDTO 列表
     */
    @Override
    public List<ControlRelatedDTO> findBaseByControlId(Long controlId, boolean filterDeleted) {
        return this.baseMapper.findBaseByControlId(controlId, filterDeleted);
    }

    /**
     * 获取控件关联
     *
     * @param controlIds    controlIds
     * @param filterDeleted filterDeleted
     * @return ControlRelatedDTO 列表
     */
    @Override
    public List<ControlRelatedDTO> findBaseByControlIds(Collection<Long> controlIds, boolean filterDeleted) {
        return this.baseMapper.findBaseByControlIds(controlIds, filterDeleted);
    }

    /**
     * 保存控件关联
     *
     * @param control             control
     * @param controlRelatedBases controlRelatedBases
     */
    @Override
    public void saveControlRelated(ApplicationFormControl control, List<ControlRelatedDTO> controlRelatedBases) {
        // 批量比较保存与逻辑删除
        List<ApplicationFormControlRelated> modifies = StreamUtil.batchCompareSave(
                controlRelatedBases,
                ControlRelatedDTO::getRelatedControlId,
                () -> this.baseMapper.findByControlId(control.getControlId(), false),
                ApplicationFormControlRelated::getRelatedControlId,
                (b, t) -> t.setIsDeleted(SwitchEnum.findIdByBoolean(b)),
                null,
                dto -> this.createControlRelated(control, dto)
        );
        // 批量保存
        logService.saveBatchAndCheck(this.baseMapper, ApplicationFormControlRelated::getControlRelatedId, modifies);
    }

    /**
     * 赋值控件关联
     *
     * @param source source
     * @param target target
     */
    @Override
    public void copyControlRelated(ApplicationFormControl source, ApplicationFormControl target) {
        // 判断源是否打开了数据关联
        if (!DefaultValueTypeEnum.isOpenRelated(source.getDefaultValueType())) {
            return;
        }
        // 只复制有效的
        List<ApplicationFormControlRelated> sources = this.baseMapper.findByControlId(source.getControlId(), true);
        Map<Long, ApplicationFormControlRelated> sourceMap = StreamUtil.toOrderlyMapK(sources, ApplicationFormControlRelated::getRelatedControlId);

        // 需要把已删除的也查询出来
        List<ApplicationFormControlRelated> targets = this.baseMapper.findByControlId(target.getControlId(), false);
        Map<Long, ApplicationFormControlRelated> targetMap = StreamUtil.toMapK(targets, ApplicationFormControlRelated::getRelatedControlId);

        List<ApplicationFormControlRelated> modifies = new ArrayList<>();
        // 编辑/新增
        sources.forEach(controlRelated -> {
            ApplicationFormControlRelated copy = this.createControlRelated(target, controlRelated);
            if (targetMap.containsKey(controlRelated.getRelatedControlId())) {
                ApplicationFormControlRelated sourceControlRelated = targetMap.get(controlRelated.getRelatedControlId());
                copy.setControlRelatedId(sourceControlRelated.getControlRelatedId());
                copy.setRelatedFormId(controlRelated.getRelatedFormId());
                copy.setRelatedControlId(controlRelated.getRelatedControlId());
                copy.setCreated(sourceControlRelated.getCreated());
                copy.setCreatorId(sourceControlRelated.getCreatorId());
                copy.setCreatorName(sourceControlRelated.getCreatorName());
            }
            modifies.add(copy);
        });
        // 删除
        modifies.addAll(StreamUtil.peekF(targets, e -> !sourceMap.containsKey(e.getRelatedControlId()), e -> e.setIsDeleted(SwitchEnum.NO.getId())));
        // 批量保存
        logService.saveBatchAndCheck(this.baseMapper, ApplicationFormControlRelated::getControlRelatedId, modifies);
    }

    private ApplicationFormControlRelated createControlRelated(ApplicationFormControl control, ApplicationFormControlRelated controlRelated) {
        return this.createControlRelated(control, controlRelated.getRelatedFormId(), controlRelated.getRelatedControlId());
    }

    private ApplicationFormControlRelated createControlRelated(ApplicationFormControl control, ControlRelatedDTO controlRelatedBase) {
        return this.createControlRelated(control, controlRelatedBase.getRelatedFormId(), controlRelatedBase.getRelatedControlId());
    }

    private ApplicationFormControlRelated createControlRelated(ApplicationFormControl control, Long relatedFormId, Long relatedControlId) {
        ApplicationFormControlRelated controlRelated = new ApplicationFormControlRelated();
        controlRelated.setEnterpriseId(control.getEnterpriseId());
        controlRelated.setFormId(control.getFormId());
        controlRelated.setControlId(control.getControlId());
        controlRelated.setControlCode(control.getControlCode());
        controlRelated.setRelatedFormId(relatedFormId);
        controlRelated.setRelatedControlId(relatedControlId);
        controlRelated.setIsDeleted(SwitchEnum.NO.getId());
        return controlRelated;
    }
}
